using Microsoft.AspNetCore.SignalR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using TerritoryGame.Domain.ValueObjects;
using TerritoryGame.Infrastructure.Data;
using System.Collections.Concurrent;
using Microsoft.EntityFrameworkCore;

namespace TerritoryGame.API.Hubs;

[Authorize]
public class GameHub : Hub
{
    private readonly ILogger<GameHub> _logger;
    private readonly TerritoryGameDbContext _db;
    
    // 静态字典来跟踪房间状态（在生产环境中应该使用Redis或数据库）
    private static readonly ConcurrentDictionary<string, RoomInfo> _rooms = new();
    private static readonly ConcurrentDictionary<string, PlayerInfo> _players = new();
    private static readonly ConcurrentDictionary<string, CancellationTokenSource> _gameTimers = new();
    
    // 头像颜色池 - 用于生成随机头像颜色
    private static readonly string[] AvatarColorPool = {
        "#FF6B6B", // 红色
        "#4ECDC4", // 青色
        "#45B7D1", // 蓝色
        "#96CEB4", // 绿色
        "#FFEAA7", // 黄色
        "#DDA0DD", // 紫色
        "#FFB347", // 橙色
        "#87CEEB", // 天蓝色
        "#98FB98", // 浅绿色
        "#F0E68C", // 卡其色
        "#FF69B4", // 粉色
        "#20B2AA", // 海绿色
        "#FF6347", // 番茄色
        "#9370DB", // 中紫色
        "#32CD32"  // 酸橙绿
    };
    
    // 跟踪已使用的头像颜色
    private static readonly ConcurrentDictionary<string, HashSet<string>> _usedAvatarColors = new();
    
    // 跟踪已使用的画笔颜色
    private static readonly ConcurrentDictionary<string, HashSet<string>> _usedBrushColors = new();

    public GameHub(ILogger<GameHub> logger, TerritoryGameDbContext db)
    {
        _logger = logger;
        _db = db;
    }
    
    // 为玩家分配头像颜色
    private string AssignAvatarColorToRoom(string roomCode)
    {
        // 获取当前房间已使用的头像颜色集合
        var roomUsedAvatarColors = _usedAvatarColors.GetOrAdd(roomCode, _ => new HashSet<string>());
        
        // 找到第一个在当前房间中未使用的头像颜色
        var availableAvatarColor = AvatarColorPool.FirstOrDefault(color => !roomUsedAvatarColors.Contains(color));
        
        if (availableAvatarColor != null)
        {
            // 将头像颜色添加到当前房间的已使用集合中
            roomUsedAvatarColors.Add(availableAvatarColor);
            _logger.LogInformation("为房间 {RoomCode} 分配头像颜色: {Color}", roomCode, availableAvatarColor);
            return availableAvatarColor;
        }
        
        // 如果当前房间的所有头像颜色都被使用，随机选择一个
        var randomAvatarColor = AvatarColorPool[new Random().Next(AvatarColorPool.Length)];
        _logger.LogWarning("房间 {RoomCode} 的头像颜色池已满，随机分配颜色: {Color}", roomCode, randomAvatarColor);
        return randomAvatarColor;
    }
    
    // 根据头像颜色生成画笔颜色
    private string GenerateBrushColorFromAvatar(string avatarColor)
    {
        // 解析头像颜色的RGB值
        var hex = avatarColor.TrimStart('#');
        var r = Convert.ToInt32(hex.Substring(0, 2), 16);
        var g = Convert.ToInt32(hex.Substring(2, 2), 16);
        var b = Convert.ToInt32(hex.Substring(4, 2), 16);
        
        // 生成稍微深一点的画笔颜色（降低亮度）
        var brushR = Math.Max(0, r - 40);
        var brushG = Math.Max(0, g - 40);
        var brushB = Math.Max(0, b - 40);
        
        // 转换为十六进制
        var brushColor = $"#{brushR:X2}{brushG:X2}{brushB:X2}";
        _logger.LogInformation("根据头像颜色 {AvatarColor} 生成画笔颜色: {BrushColor}", avatarColor, brushColor);
        
        return brushColor;
    }
    
    // 为房间分配颜色（现在分配头像颜色，然后生成画笔颜色）
    private (string avatarColor, string brushColor) AssignColorsToRoom(string roomCode)
    {
        var avatarColor = AssignAvatarColorToRoom(roomCode);
        var brushColor = GenerateBrushColorFromAvatar(avatarColor);
        
        // 将画笔颜色添加到房间的已使用画笔颜色集合中
        var roomUsedBrushColors = _usedBrushColors.GetOrAdd(roomCode, _ => new HashSet<string>());
        roomUsedBrushColors.Add(brushColor);
        
        _logger.LogInformation("为房间 {RoomCode} 分配颜色 - 头像: {AvatarColor}, 画笔: {BrushColor}", roomCode, avatarColor, brushColor);
        
        return (avatarColor, brushColor);
    }
    
    // 释放房间中的头像颜色
    private void ReleaseAvatarColorFromRoom(string roomCode, string avatarColor)
    {
        if (_usedAvatarColors.TryGetValue(roomCode, out var usedColors))
        {
            usedColors.Remove(avatarColor);
            _logger.LogInformation("从房间 {RoomCode} 释放头像颜色: {Color}", roomCode, avatarColor);
        }
    }
    
    // 释放房间中的画笔颜色
    private void ReleaseBrushColorFromRoom(string roomCode, string brushColor)
    {
        if (_usedBrushColors.TryGetValue(roomCode, out var usedColors))
        {
            usedColors.Remove(brushColor);
            _logger.LogInformation("从房间 {RoomCode} 释放画笔颜色: {Color}", roomCode, brushColor);
        }
    }
    
    // 释放房间中的颜色（兼容性方法）
    private void ReleaseColorFromRoom(string roomCode, string color)
    {
        // 根据颜色类型决定释放哪种颜色
        if (AvatarColorPool.Contains(color))
        {
            ReleaseAvatarColorFromRoom(roomCode, color);
        }
        else
        {
            ReleaseBrushColorFromRoom(roomCode, color);
        }
    }

    public async Task CreateRoom(string roomCode, string roomName, int maxPlayers, string password, string playerId, string nickname, string playerColor = "")
    {
        _logger.LogInformation("Creating room {RoomCode} with name {RoomName} by player {PlayerId}", roomCode, roomName, playerId);
        
        // 检查房间是否已存在
        if (_rooms.ContainsKey(roomCode))
        {
            await Clients.Caller.SendAsync("RoomAlreadyExists", new { RoomCode = roomCode });
            return;
        }
        
        // 创建新房间
        var roomInfo = new RoomInfo
        {
            RoomCode = roomCode,
            RoomName = roomName,
            MaxPlayers = maxPlayers,
            Password = password,
            OwnerId = playerId,
            CreatedAt = DateTime.UtcNow
        };
        
        // 为房主自动分配头像颜色和画笔颜色
        var (avatarColor, brushColor) = AssignColorsToRoom(roomCode);
        
        // 添加房主到房间
        var userId = Context.User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
                     ?? Context.User?.FindFirst(System.IdentityModel.Tokens.Jwt.JwtRegisteredClaimNames.Sub)?.Value;
        var playerInfo = new PlayerInfo
        {
            PlayerId = playerId,
            Nickname = nickname,
            AvatarColor = avatarColor,
            BrushColor = brushColor,
            ConnectionId = Context.ConnectionId,
            JoinedAt = DateTime.UtcNow,
            UserId = userId
        };
        
        _rooms[roomCode] = roomInfo;
        _players[Context.ConnectionId] = playerInfo;
        roomInfo.Players[playerId] = playerInfo;
        
        // 添加到SignalR组
        await Groups.AddToGroupAsync(Context.ConnectionId, roomCode);
        
        // 通知房主房间创建成功
        await Clients.Caller.SendAsync("RoomCreated", new
        {
            RoomCode = roomCode,
            RoomName = roomName,
            MaxPlayers = maxPlayers,
            PlayerCount = 1,
            IsOwner = true,
            AvatarColor = avatarColor, // 包含分配的头像颜色
            BrushColor = brushColor    // 包含生成的画笔颜色
        });
        
        // 发送房间状态更新
        await SendRoomStateUpdate(roomCode);
    }

    public async Task JoinRoom(string roomCode, string playerId, string nickname, string playerColor = "", string password = "")
    {
        _logger.LogInformation("Player {PlayerId} ({Nickname}) joining room {RoomCode}", playerId, nickname, roomCode);
        
        // 检查房间是否存在
        if (!_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            await Clients.Caller.SendAsync("RoomNotFound", new { RoomCode = roomCode });
            return;
        }
        
        // 检查房间密码
        if (!string.IsNullOrEmpty(roomInfo.Password) && roomInfo.Password != password)
        {
            await Clients.Caller.SendAsync("InvalidPassword", new { RoomCode = roomCode });
            return;
        }
        
        // 检查房间是否已满
        if (roomInfo.Players.Count >= roomInfo.MaxPlayers)
        {
            await Clients.Caller.SendAsync("RoomFull", new { RoomCode = roomCode, MaxPlayers = roomInfo.MaxPlayers });
            return;
        }
        
        // 添加到SignalR组
        await Groups.AddToGroupAsync(Context.ConnectionId, roomCode);
        
        // 为玩家自动分配头像颜色和画笔颜色
        var (assignedAvatarColor, assignedBrushColor) = AssignColorsToRoom(roomCode);
        
        // 更新房间信息
        var userId = Context.User?.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)?.Value
                     ?? Context.User?.FindFirst(System.IdentityModel.Tokens.Jwt.JwtRegisteredClaimNames.Sub)?.Value;
        var playerInfo = new PlayerInfo
        {
            PlayerId = playerId,
            Nickname = nickname,
            AvatarColor = assignedAvatarColor,
            BrushColor = assignedBrushColor,
            ConnectionId = Context.ConnectionId,
            JoinedAt = DateTime.UtcNow,
            UserId = userId
        };
        
        _players[Context.ConnectionId] = playerInfo;
        roomInfo.Players[playerId] = playerInfo;
        
        // 通知房间内所有玩家
        await Clients.Group(roomCode).SendAsync("PlayerJoined", new
        {
            PlayerId = playerId,
            Nickname = nickname,
            AvatarColor = assignedAvatarColor, // 使用分配后的头像颜色
            BrushColor = assignedBrushColor,  // 使用生成的画笔颜色
            ConnectionId = Context.ConnectionId,
            JoinedAt = DateTime.UtcNow
        });
        
        // 发送房间状态更新
        await SendRoomStateUpdate(roomCode);
        
        // 发送欢迎消息
        await Clients.Caller.SendAsync("WelcomeMessage", new
        {
            Message = $"欢迎来到房间 {roomInfo.RoomName}！",
            RoomCode = roomCode,
            RoomName = roomInfo.RoomName,
            PlayerCount = roomInfo.Players.Count,
            MaxPlayers = roomInfo.MaxPlayers
        });

        // 向加入者发送当前房间的完整快照，确保与房主加载同一份数据
        await Clients.Caller.SendAsync("RoomInfo", new
        {
            RoomCode = roomCode,
            RoomName = roomInfo.RoomName,
            OwnerId = roomInfo.OwnerId,
            MaxPlayers = roomInfo.MaxPlayers,
            PlayerCount = roomInfo.Players.Count,
            GameStatus = roomInfo.GameStatus,
            GameStartedAt = roomInfo.GameStartedAt,
            GameEndedAt = roomInfo.GameEndedAt,
            GameDuration = roomInfo.GameDuration,
            BrushSize = roomInfo.BrushSize,
            Players = roomInfo.Players.Values.Select(p => new
            {
                p.PlayerId,
                p.Nickname,
                p.AvatarColor,
                p.BrushColor,
                p.JoinedAt
            }).ToList()
        });
    }

    public async Task LeaveRoom(string roomCode, string playerId)
    {
        _logger.LogInformation("Player {PlayerId} leaving room {RoomCode}", playerId, roomCode);
        
        // 从SignalR组移除
        await Groups.RemoveFromGroupAsync(Context.ConnectionId, roomCode);
        
        // 更新房间信息并释放颜色
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            if (roomInfo.Players.TryRemove(playerId, out var leavingPlayer))
            {
                // 释放玩家使用的颜色
                ReleaseColorFromRoom(roomCode, leavingPlayer.AvatarColor);
                ReleaseColorFromRoom(roomCode, leavingPlayer.BrushColor);

                // 将离开的玩家记录到历史玩家集合中，确保赛后能统计
                roomInfo.PastPlayers[leavingPlayer.PlayerId] = leavingPlayer;
            }
            
            // 如果房间空了，清理房间
            if (roomInfo.Players.IsEmpty)
            {
                // 结束可能存在的游戏计时器
                if (_gameTimers.TryRemove(roomCode, out var cts))
                {
                    try { cts.Cancel(); } catch {}
                    cts.Dispose();
                }
                _rooms.TryRemove(roomCode, out _);
                _usedAvatarColors.TryRemove(roomCode, out _); // 清理房间的头像颜色记录
                _usedBrushColors.TryRemove(roomCode, out _);  // 清理房间的画笔颜色记录
                _logger.LogInformation("Room {RoomCode} is now empty and has been cleaned up", roomCode);
            }
        }
        
        // 清理玩家信息
        _players.TryRemove(Context.ConnectionId, out _);
        
        // 通知房间内其他玩家
        await Clients.Group(roomCode).SendAsync("PlayerLeft", new
        {
            PlayerId = playerId,
            ConnectionId = Context.ConnectionId,
            LeftAt = DateTime.UtcNow
        });
        
        // 发送房间状态更新
        await SendRoomStateUpdate(roomCode);
    }

    public async Task UpdateGameSettings(string roomCode, string playerId, int gameDuration, int brushSize)
    {
        _logger.LogInformation("Updating game settings in room {RoomCode} by player {PlayerId}: duration={Duration}s, brushSize={BrushSize}", 
            roomCode, playerId, gameDuration, brushSize);
        
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            // 检查是否是房主
            if (roomInfo.OwnerId != playerId)
            {
                await Clients.Caller.SendAsync("Unauthorized", new { Message = "只有房主可以修改游戏设置" });
                return;
            }
            
            // 更新游戏设置
            roomInfo.GameDuration = gameDuration;
            roomInfo.BrushSize = brushSize;
            
            // 广播设置更新给房间内所有玩家
            await Clients.Group(roomCode).SendAsync("GameSettingsUpdated", new
            {
                GameDuration = gameDuration,
                BrushSize = brushSize,
                UpdatedBy = playerId,
                UpdatedAt = DateTime.UtcNow
            });
            
            // 同时更新房间状态
            await SendRoomStateUpdate(roomCode);
        }
        else
        {
            await Clients.Caller.SendAsync("RoomNotFound", new { RoomCode = roomCode });
        }
    }

    public async Task StartGame(string roomCode, int gameDuration = 180, int brushSize = 12)
    {
        _logger.LogInformation("Game starting in room {RoomCode} with duration {Duration}s and brush size {BrushSize}", 
            roomCode, gameDuration, brushSize);
        
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            roomInfo.GameStatus = GameStatus.Playing;
            roomInfo.GameStartedAt = DateTime.UtcNow;
            
            // 存储游戏设置
            roomInfo.GameDuration = gameDuration;
            roomInfo.BrushSize = brushSize;

            // 启动/重置服务器端倒计时，确保无人触发时也会结算
            if (_gameTimers.TryRemove(roomCode, out var existingCts))
            {
                try { existingCts.Cancel(); } catch {}
                existingCts.Dispose();
            }
            var cts = new CancellationTokenSource();
            _gameTimers[roomCode] = cts;
            _ = Task.Run(async () =>
            {
                try
                {
                    await Task.Delay(TimeSpan.FromSeconds(gameDuration), cts.Token);
                    if (!cts.Token.IsCancellationRequested)
                    {
                        await EndGame(roomCode);
                    }
                }
                catch (TaskCanceledException) { }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "Server timer failed for room {RoomCode}", roomCode);
                }
            });
        }
        
        await Clients.Group(roomCode).SendAsync("GameStarted", new
        {
            StartedAt = DateTime.UtcNow,
            PlayerCount = roomInfo?.Players.Count ?? 0,
            GameDuration = gameDuration,
            BrushSize = brushSize
        });
    }

    public async Task Paint(string roomCode, string playerId, int x, int y, string color, int brushSize, string tool)
    {
        _logger.LogDebug("Player {PlayerId} painting at ({X}, {Y}) with {Tool} size {BrushSize} in room {RoomCode}", 
            playerId, x, y, tool, brushSize, roomCode);
        
        await Clients.Group(roomCode).SendAsync("PaintActionReceived", new
        {
            PlayerId = playerId,
            X = x,
            Y = y,
            Color = color,
            BrushSize = brushSize,
            Tool = tool,
            Timestamp = DateTime.UtcNow
        });
    }

    public async Task PaintWithData(string roomCode, string playerId, object paintData)
    {
        _logger.LogDebug("Player {PlayerId} painting with data in room {RoomCode}", playerId, roomCode);
        
        // 将paintData转换为匿名对象，附带playerId，保持原始属性名
        await Clients.Group(roomCode).SendAsync("PaintActionReceived", paintData);
    }

    public async Task UpdateArea(string roomCode, string playerId, double area)
    {
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            if (roomInfo.Players.TryGetValue(playerId, out var p))
            {
                p.Area = area;
            }
        }

        await Clients.Group(roomCode).SendAsync("AreaUpdated", new
        {
            PlayerId = playerId,
            Area = area,
            Timestamp = DateTime.UtcNow
        });
    }

    public async Task EndGame(string roomCode)
    {
        _logger.LogInformation("Game ending in room {RoomCode}", roomCode);
        
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            // 防止重复结束游戏
            if (roomInfo.GameStatus == GameStatus.Finished)
            {
                _logger.LogInformation("Game already ended in room {RoomCode}, skipping", roomCode);
                return;
            }
            
            roomInfo.GameStatus = GameStatus.Finished;
            roomInfo.GameEndedAt = DateTime.UtcNow;

            // 停止并清理服务器端计时器
            if (_gameTimers.TryRemove(roomCode, out var cts))
            {
                try { cts.Cancel(); } catch {}
                cts.Dispose();
            }

            try
            {
                // 检查是否已经存在历史记录
                var existingHistory = await _db.GameHistories
                    .FirstOrDefaultAsync(h => h.RoomCode == roomCode);
                
                if (existingHistory != null)
                {
                    _logger.LogInformation("Game history already exists for room {RoomCode}, skipping creation", roomCode);
                    return;
                }
                
                // 汇总当前与历史玩家，确保离开玩家也能被记录
                var allPlayers = roomInfo.Players.Values
                    .Concat(roomInfo.PastPlayers.Values)
                    .GroupBy(p => p.PlayerId)
                    .Select(g => g.OrderByDescending(x => x.JoinedAt).First())
                    .ToList();

                // 构建历史
                var history = new TerritoryGame.Domain.Entities.GameHistory
                {
                    Id = Guid.NewGuid(),
                    RoomCode = roomInfo.RoomCode,
                    RoomName = roomInfo.RoomName,
                    EndedAt = roomInfo.GameEndedAt ?? DateTime.UtcNow,
                    DurationSeconds = roomInfo.GameDuration,
                };

                // 根据面积从高到低分配名次
                var ranked = allPlayers
                    .OrderByDescending(p => p.Area)
                    .Select((p, idx) => new { Player = p, Rank = idx + 1 })
                    .ToList();

                foreach (var item in ranked)
                {
                    history.Players.Add(new TerritoryGame.Domain.Entities.GameHistoryPlayer
                    {
                        Id = Guid.NewGuid(),
                        GameHistoryId = history.Id,
                        PlayerId = item.Player.PlayerId,
                        UserId = item.Player.UserId,
                        Nickname = item.Player.Nickname,
                        Color = item.Player.BrushColor,
                        Area = item.Player.Area,
                        Rank = item.Rank
                    });
                }

                var winner = history.Players.OrderByDescending(x => x.Area).FirstOrDefault();
                if (winner != null)
                {
                    history.WinnerPlayerId = winner.PlayerId;
                    history.WinnerNickname = winner.Nickname;
                    history.WinnerColor = winner.Color;
                }

                _db.GameHistories.Add(history);
                await _db.SaveChangesAsync();
                
                _logger.LogInformation("Game history created successfully for room {RoomCode}", roomCode);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to persist game history for room {RoomCode}", roomCode);
            }
        }
        
        await Clients.Group(roomCode).SendAsync("GameEnded", new
        {
            EndedAt = DateTime.UtcNow
        });
    }

    public async Task SendChatMessage(string roomCode, string playerId, string message)
    {
        if (string.IsNullOrWhiteSpace(message))
            return;
            
        await Clients.Group(roomCode).SendAsync("ChatMessage", new
        {
            PlayerId = playerId,
            Message = message.Trim(),
            Timestamp = DateTime.UtcNow
        });
    }

    public async Task GetRoomInfo(string roomCode)
    {
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            await Clients.Caller.SendAsync("RoomInfo", new
            {
                RoomCode = roomCode,
                RoomName = roomInfo.RoomName,
                MaxPlayers = roomInfo.MaxPlayers,
                OwnerId = roomInfo.OwnerId,
                PlayerCount = roomInfo.Players.Count,
                GameStatus = roomInfo.GameStatus,
                GameStartedAt = roomInfo.GameStartedAt,
                GameEndedAt = roomInfo.GameEndedAt,
                GameDuration = roomInfo.GameDuration,
                BrushSize = roomInfo.BrushSize,
                Players = roomInfo.Players.Values.Select(p => new
                {
                    p.PlayerId,
                    p.Nickname,
                    p.AvatarColor,
                    p.BrushColor,
                    p.JoinedAt
                }).ToList()
            });
        }
        else
        {
            await Clients.Caller.SendAsync("RoomNotFound", new { RoomCode = roomCode });
        }
    }

    public async Task Ping()
    {
        await Clients.Caller.SendAsync("Pong", new { Timestamp = DateTime.UtcNow });
    }

    private async Task SendRoomStateUpdate(string roomCode)
    {
        if (_rooms.TryGetValue(roomCode, out var roomInfo))
        {
            await Clients.Group(roomCode).SendAsync("RoomStateUpdated", new
            {
                RoomCode = roomCode,
                RoomName = roomInfo.RoomName,
                MaxPlayers = roomInfo.MaxPlayers,
                OwnerId = roomInfo.OwnerId,
                PlayerCount = roomInfo.Players.Count,
                GameStatus = roomInfo.GameStatus,
                GameDuration = roomInfo.GameDuration,
                BrushSize = roomInfo.BrushSize,
                Players = roomInfo.Players.Values.Select(p => new
                {
                    p.PlayerId,
                    p.Nickname,
                    p.AvatarColor,
                    p.BrushColor,
                    p.JoinedAt
                }).ToList()
            });
        }
    }

    public override async Task OnConnectedAsync()
    {
        _logger.LogInformation("Client connected: {ConnectionId}", Context.ConnectionId);
        await base.OnConnectedAsync();
        
        // 发送连接确认
        await Clients.Caller.SendAsync("Connected", new
        {
            ConnectionId = Context.ConnectionId,
            Timestamp = DateTime.UtcNow
        });
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        _logger.LogInformation("Client disconnected: {ConnectionId}", Context.ConnectionId);
        
        // 清理断开连接的玩家
        if (_players.TryRemove(Context.ConnectionId, out var playerInfo))
        {
            // 找到玩家所在的房间并通知其他玩家
            foreach (var room in _rooms.Values)
            {
                if (room.Players.TryRemove(playerInfo.PlayerId, out var disconnectedPlayer))
                {
                    // 释放玩家使用的颜色
                    ReleaseColorFromRoom(room.RoomCode, disconnectedPlayer.AvatarColor);
                    ReleaseColorFromRoom(room.RoomCode, disconnectedPlayer.BrushColor);
                    // 记录到历史玩家集合
                    room.PastPlayers[disconnectedPlayer.PlayerId] = disconnectedPlayer;
                    
                    await Clients.Group(room.RoomCode).SendAsync("PlayerDisconnected", new
                    {
                        PlayerId = playerInfo.PlayerId,
                        Nickname = playerInfo.Nickname,
                        DisconnectedAt = DateTime.UtcNow
                    });
                    
                    await SendRoomStateUpdate(room.RoomCode);
                    break;
                }
            }
        }
        
        await base.OnDisconnectedAsync(exception);
    }
}

// 辅助类
public class RoomInfo
{
    public string RoomCode { get; set; } = string.Empty;
    public string RoomName { get; set; } = string.Empty; // 添加房间名称
    public int MaxPlayers { get; set; } = 6; // 添加最大玩家数
    public string Password { get; set; } = string.Empty; // 添加房间密码
    public string OwnerId { get; set; } = string.Empty; // 添加房主ID
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // 添加创建时间
    public ConcurrentDictionary<string, PlayerInfo> Players { get; set; } = new();
    public GameStatus GameStatus { get; set; } = GameStatus.Waiting;
    public DateTime? GameStartedAt { get; set; }
    public DateTime? GameEndedAt { get; set; }
    public int GameDuration { get; set; } = 180; // 默认3分钟
    public int BrushSize { get; set; } = 12; // 默认中等画笔
    public ConcurrentDictionary<string, PlayerInfo> PastPlayers { get; set; } = new();
}

public class PlayerInfo
{
    public string PlayerId { get; set; } = string.Empty;
    public string Nickname { get; set; } = string.Empty;
    public string AvatarColor { get; set; } = string.Empty;  // 头像颜色
    public string BrushColor { get; set; } = string.Empty;   // 画笔颜色
    public string ConnectionId { get; set; } = string.Empty;
    public DateTime JoinedAt { get; set; }
    public double Area { get; set; }
    public string? UserId { get; set; }
}

public enum GameStatus
{
    Waiting,
    Playing,
    Finished
}
